
/* GCSx
** RESOLUTION.CPP
**
** Resolution-selection dialog
*/

/*****************************************************************************
** Copyright (C) 2003-2006 Janson
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
*****************************************************************************/

#include "all.h"

ResolutionDialog* ResolutionDialog::dialog = NULL;

ResolutionDialog* ResolutionDialog::create() { start_func
    if (!dialog) {
        dialog = new ResolutionDialog();
    }
    return dialog;
}

void ResolutionDialog::destroy() { start_func
    if (dialog) {
        delete dialog;
        dialog = NULL;
    }
}

ResolutionDialog::ResolutionDialog() : Dialog("Select Resolution") { start_func
    resSelection = 1;
    initialized = 0;
}

void ResolutionDialog::chooseResolution() { start_func
    if (!initialized) {
        Widget* w = NULL;
        WListBox* l = NULL;
        SDL_Rect** vidModes = NULL;
        
        // Start with best format
        SDL_PixelFormat format = *(SDL_GetVideoInfo()->vfmt);
        // (max 32 bpp)
        if (format.BitsPerPixel > 32) {
            format.BitsPerPixel = 32;
            format.BytesPerPixel = 4;
        }
    
        w = new WStatic(ID_LABEL, "\tResolution:");
        w->addTo(this);
        
        l = new WListBox(ID_LISTBOX, &resSelection, 0, -1, 10);
        
        // Windowed option
        int found = 1;
        l->addItem(ListEntry("Windowed mode", found, 0, 0, 0));
        l->addItem(ListEntry("Windowed (no resize)", ++found, 0, 0, 0));
        
        if (!screenFullscreen()) {
            if (screenResizable()) {
                resSelection = 1;
            }
            else {
                resSelection = 2;
            }
        }
        
        char resDesc[80];
        for (;;) {
            vidModes = SDL_ListModes(&format, SDL_FULLSCREEN|SDL_SWSURFACE);
            if (vidModes == (SDL_Rect**)-1) {
                // We can't handle SDL's "any resolution is OK" concept
                fatalCrash(0, "Unlimited video modes- unhandled");
            }
            if (vidModes) {
                for (int pos = 0; vidModes[pos]; ++pos) {
                    if ((vidModes[pos]->w >= 320) && (vidModes[pos]->h >= 240)) {
                        ++found;
                        sprintf(resDesc, "%d x %d x %dbpp", vidModes[pos]->w, vidModes[pos]->h, format.BitsPerPixel);
                        // (current format?)
                        if ((screenFullscreen()) &&
                            (vidModes[pos]->w == screenWidth) &&
                            (vidModes[pos]->h == screenHeight) &&
                            (format.BitsPerPixel == screenBits())) {
                            resSelection = found;
                        }
                        l->addItem(ListEntry(resDesc, found, vidModes[pos]->w, vidModes[pos]->h, format.BitsPerPixel));
                    }
                }
            }
            // Switch downward from 32 to 24 to 16 to 15 bits
            if ((format.BitsPerPixel == 32) || (format.BitsPerPixel == 24)) {
                format.BitsPerPixel -= 8;
                format.BytesPerPixel -= 1;
            }
            else if (format.BitsPerPixel == 16) {
                format.BitsPerPixel -= 1;
                format.BytesPerPixel -= 1;
            }
            else break;
        }
        l->addTo(this);
        
        w = new WButton(ID_OK, messageBoxOK, Dialog::BUTTON_OK);
        w->addTo(this);

        w = new WButton(ID_CANCEL, messageBoxCancel, Dialog::BUTTON_CANCEL);
        w->addTo(this);
        
        makePretty(2, 0);
        
        initialized = 1;
    }

    // Hit OK?
    if (runModal() == ID_OK) {
        // Catch non-fatal video errors
        try {
            if ((resSelection == 1) || (resSelection == 2)) {
                selectVideoMode(screenWidth, screenHeight, -1, 0, resSelection == 1 ? 1 : 0);
            }
            else {
                assert(findWidget(ID_LISTBOX));
                const ListEntry* res = dynamic_cast<WListBox*>(findWidget(ID_LISTBOX))->findEntry(resSelection);
                assert(res);
                selectVideoMode(res->code1, res->code2, res->code3, 1, 0);
            }
        }
        catch (const VideoException& e) {
            guiErrorBox(string(e.details), errorTitleVideo);
        }
    }
}

